package com.doubao.doubao_admin.utils;

import cn.hutool.core.lang.Console;
import io.jsonwebtoken.*;
import org.slf4j.LoggerFactory;

import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.security.Key;
import java.text.SimpleDateFormat;
import java.util.*;
//import java.util.logging.Logger;

/**
 * JSON Web Token 工具类
 *
 * 国服最强JWT生成Token做登录校验讲解
 * https://blog.csdn.net/u011277123/article/details/78918390?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-8.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-8.no_search_link
 */
public class JwtUtils {

//    private static final Logger logger = (Logger) LoggerFactory.getLogger(JwtUtils.class);
    /**
     * key（按照签名算法的字节长度设置key）
     */
    public static final String SECRET_KEY = "0123456789_0123456789_0123456789";
    /**
     * 过期时间（毫秒单位）
     */
    public static final long TOKEN_EXPIRE_MILLIS = 1000 * 60 * 60L;

    public static final String HEADER_STRING = "Authorization";
    public static final String TOKEN_PREFIX = "Bearer ";
    public static final String USER_JNAME = "userName";
    public static final String SECRET = "ThisIsSecret ";

    /**
     * 创建token
     *
     * @param
     * @return
     */
    public static String createToken(String userId) {
        HashMap<String, Object> map = new HashMap<>();

        map.put(USER_JNAME, userId);
        long currentTimeMillis = System.currentTimeMillis();
        return Jwts.builder()
                .setId(UUID.randomUUID().toString())
                .setIssuedAt(new Date(currentTimeMillis))    // 设置签发时间
                .setExpiration(new Date(currentTimeMillis + TOKEN_EXPIRE_MILLIS))   // 设置过期时间
                .addClaims(map)
                .signWith(SignatureAlgorithm.HS256, SECRET)
                .compact();
    }

    public static HttpServletRequest validateTokenAndAddUserIdToHeader(HttpServletRequest request){
        String token = request.getHeader(HEADER_STRING);

        if (token != null){
            try {
                Map<String,Object> body = Jwts.parser()
                        .setSigningKey(SECRET)
                        .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
                        .getBody();
                //这里创建了一个HttpServletRequest对象并且返回了
                return new CustomHttpServletRequest(request,body);
            }catch (Exception e){
                Console.log("e:" + e);
                throw  new TokenValidationException(e.getMessage());
            }
        }else {
            throw  new TokenValidationException("Missing token");

        }

    }

    /**
     * 自定义的request对象必须提供一个getHeaders的方法，看传过来的claims的map里是否包含这个key，如果包含
     * 就拿到对应的value，返回回去
     */
    public static class CustomHttpServletRequest extends HttpServletRequestWrapper{
        private Map<String,String> claims;

        public CustomHttpServletRequest(HttpServletRequest request,Map<String,?> claims){

            super(request);
            this.claims = new HashMap<>();
            claims.forEach((k,v) -> this.claims.put(k, String.valueOf(v)));
        }

        @Override
        public Enumeration<String> getHeaders(String name){

            if (claims != null && claims.containsKey(name)){
                return Collections.enumeration(Arrays.asList(claims.get(name)));
            }
            return super.getHeaders(name);
        }
    }

    static class TokenValidationException extends RuntimeException {
        public TokenValidationException(String msg) {
            super(msg);
        }
    }
    /**
     * 验证token
     *
     * @param token
     * @return 0 验证成功，1、2、3、4、5 验证失败
     */
    public static int verifyToken(String token) {
        SimpleDateFormat f=new SimpleDateFormat("yyyy 年 MM 月 dd 日 HH 点 mm 分 ss 秒");

        try {
//            Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token);
            Jwts.parser()
                    .setSigningKey(SECRET)
                    .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
                    .getBody();
            return 0;
        } catch (ExpiredJwtException e) {
            e.printStackTrace();
            return 1;
        } catch (UnsupportedJwtException e) {
            e.printStackTrace();
            return 2;
        } catch (MalformedJwtException e) {
            e.printStackTrace();
            return 3;
        } catch (SignatureException e) {
            e.printStackTrace();
            return 4;
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
            return 5;
        }
    }

    /**
     * 解析token
     *
     * @param token
     * @return
     */
    public static Map<String, Object> parseToken(String token) {
// 得到DefaultJwtParser
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(generateKey()) // 设置标识名
                    .parseClaimsJws(token)  //解析token
                    .getBody();
        } catch (ExpiredJwtException e) {
            claims = e.getClaims();
        }
        return claims;

    }

    //不管是否过期，都返回claims对象
    public Claims parseJwt(String token) {
        Claims claims;
        try {
            claims = Jwts.parser()
                    .setSigningKey(generateKey()) // 设置标识名
                    .parseClaimsJws(token)  //解析token
                    .getBody();
        } catch (ExpiredJwtException e) {
            claims = e.getClaims();
        }
        return claims;
    }

    /**
     * 生成安全密钥
     *
     * @return
     */
    public static Key generateKey() {
        return new SecretKeySpec(SECRET_KEY.getBytes(), SignatureAlgorithm.HS256.getJcaName());
    }
}
    /**
     * 获取token中信息 username
     */

